%
%  untitled
%
%  Created by Steven Harms on 2008-03-22.
%  Copyright (c) 2008 __MyCompanyName__. All rights reserved.
%
\documentclass[]{article}

% Use utf-8 encoding for foreign characters
\usepackage[utf8]{inputenc}

% Setup for fullpage use
\usepackage{fullpage}

% Uncomment some of the following if you use the features
%
% Running Headers and footers
%\usepackage{fancyhdr}

% Multipart figures
%\usepackage{subfigure}

% More symbols
%\usepackage{amsmath}
%\usepackage{amssymb}
%\usepackage{latexsym}

% Surround parts of graphics with box
\usepackage{boxedminipage}

% Package for including code in the document
\usepackage{listings}

% If you want to generate a toc for each chapter (use with book)
\usepackage{minitoc}

% This is now the recommended way for checking for PDFLaTeX:
\usepackage{ifpdf}

%\newif\ifpdf
%\ifx\pdfoutput\undefined
%\pdffalse % we are not running PDFLaTeX
%\else
%\pdfoutput=1 % we are running PDFLaTeX
%\pdftrue
%\fi

\ifpdf
\usepackage[pdftex]{graphicx}
\else
\usepackage{graphicx}
\fi
\title{Mailguard Appliance Deployment Guide}
\author{ Steven G. Harms (stharms@cisco.com) }

\date{2008-03-20}

\begin{document}


\maketitle

\begin{abstract}
	A description of how to take the Mailguard source code and configure it on a generic Linux machine such that one creates a ``Mailguard appliance''.  The article includes download, basic configuration of the application, configuration of the Sendmail environment, deployment of an auxiliary web environment, and basic testing.
	
\end{abstract}

\large
\section* {INTRODUCTION} % (fold)
\label{sec:introduction}

This document assumes that you have already attempted the basic demo install that can be found in the README and that you desire to create a ``mailguard appliance'' server.  

I've tried to make this as simple as possible, but you should be able to do
this in about a half hour.  I've had several other admins test this out and
they all finished in about that same amount of time.  Let's get started.

% section introduction (end)

\section*{SPECIFICATION} % (fold)
\label{sec:specification}


I am building an appliance called ``mailguard.cisco.com''.  Mail will be routed to this machine via a larger backbone routing system.  That system will have chosen to route to this machine by virtue of an alias line like:

\begin{quote}
	\textbf{mailguard-list: mailguard-list@mailguard.cisco.com}
\end{quote}


Conversely, when a mail message has run the mailguard gauntlet successfully,
the mail will be addressed to ``original-listname-filtered'' and routed back to the aforementioned backbone smart-host (i.e. the DS value specified in the sendmail.cf).  This design keeps the Mailguard appliance host fairly dumb, but the smart hosts, rightly, smart.

A way of conceiving the alias line on the smart host would be:

\begin{quote}
	\textbf{mailguard-list-filtered: :include:/list/source/directory/mailguard-list}
\end{quote}


The mailguard appliance machine (``mailguard.cisco.com'') will have a custom
mailer defined such that anything addressed @mailguard.cisco.com will route to
the custom mailer which feeds to the Mailguard Perl script.

Mail queued will be accessible via the web tools for escrow, forwarding, deletion, or rejection with comments.

You have access to superuser privileges on this machine and can sudo,
get access as root, etc.  I have bracketed those commands with \textbf{SU}.

Let's get started!
% section specification (end)

\section*{Step-By-Step Installation} % (fold)

The installation falls into SOME NUMBER HERE major actions, and I have broken them each into subsections.  These sections are:

\begin{enumerate}
	\item Retrieve the source and configure the system
	\item Configure the Sendmail Daemon
	\item Test the Sendmail / OS pairing
	\item Deploy the web scripts
\end{enumerate}

\subsection*{Source Retrieval and OS Configuration} % (fold)
\label{sub:source_retrieval_and_os_configuration}

\begin{enumerate}
	\item  Log into whitebox machine ``mailguard'' as non-privileged user ``stharms''.  Machine has subversion installed.
	
	\item  \textbf{SU} Create a Unix group called \underline{mailguard}.  Add to this group the account your mail agent runs as, as well as your non privileged user account.  This is necessary so that the sendmail daemon can read the Mailguard queue and the mailguard cacheDB.  Logout and log back in and verify membership in group
by issuing ``groups'' command.
	
	\item Execute: \textbf{svn export https://cmailguard.googlecode.com/svn/trunk/ cmailguard}
	
\vskip 0.5em
\textbf{Comment}:  I chose to export the source such that any change I made here did
not get reflected back to the subversion repository.  if don't have commit
access this isn't a problem, but you should be careful anyway.

\vskip 0.5em
\textbf{Alternatives}: Alternative download sources would be:
\begin{itemize}
	\item A release revision number: https://cmailguard.googlecode.com/svn/branches/release-number
	\item A download from the ``releases'' page at http://code.google.com/p/cmailguard
\end{itemize}
	

\item For the purposes of this document, I'm going to assume you did this in your home directory.  Thus ./cmailguard means ``the SVN export in your homedir''.

	
\item  \textbf{SU} cp -r ./cmailguard/additional\_libraries/ ./cmailguard/mailguard/ /opt/

\vskip 0.5em
\textbf{Comment:}Make sure you're not changing the ./cmailguard if you're pulling up these long paths in your command history 8) 
	
\item  \textbf{SU} chgrp -R mailguard /opt/mailguard/
/opt/additional\_libraries

\item  \textbf{SU} chmod -R g+rwx /opt/mailguard/ /opt/additional\_libraries/

\vskip 0.5em
\textbf{Comment}:  Move the critical directories to the appropriate parent directory.  Set the permissions on the source files as appropriate.
	
	\item cd /opt/mailguard
	
	\item Edit \textbf{CONFIGURE.sh} with your favorite text editor and set path to the MAILGUARD\_ROOT variable to \underline{MAILGUARD\_ROOT="/opt"}
	
\item Run \textbf{bash -x CONFIGURE.sh} ( I used -x to get debugging output, not strictly required ).  I delete this script to get rid of it cluttering the top-level directory.


\item cd /opt/additional\_libraries/

\item \textbf{SU} bash ./INSTALL.sh 
\vskip 0.5em
\textbf{Comment:}  I did the following steps while this was running, it may take a few minutes ).  I ran this with superuser privileges so that all the Perl package magic could happen without my intervention.  This may take a moment or two depending on your system, so you may want to do	something else.

\item You may now safely remove the /opt/additional\_libraries directory.  You won't need it again.

\item   Wow, that's swell, our initial install is looking good.  Now we need to
   build custom sendmail.cf for appliance.  This varies distribution by
   distribution, but here's how it worked on my Red Hat Enterprise Linux-based
   system.  

% section source_retrieval_and_os_configuration (end)

\subsection*{Configure the Sendmail Daemon} % (fold)
\label{sec:configure_the_sendmail_daemon}


\item \textbf{cp \$MGHOME/cmailguard/sendmail/mailguard.mc \\ /usr/share/sendmail-cf/cf/}
\item cp \textbf{\$MGHOME/cmailguard/sendmail/mailguard.m4 \\ /usr/share/sendmail-cf/mailer/}


\item Evaluate the default \textbf{mailguard.m4}: 
\vskip 0.5em
   \textbf{Comment:} Values you may want to change would be the MAILGUARD\_SCRIPT\_LOC value (
   maybe you need to install in /usr/local )


\item Edit the mailguard.mc
\vskip 0.5em
   \textbf{Comment:} You \textbf{WILL NEED TO MAKE EDITS} to mailguard.mc, but don't worry, they're
   small.

\begin{enumerate}
	\item Change ``mailguard.YOURDOMAIN.com'' to be the name of the appliance
  machine that you're going to run mailguard on.  I changed mine to
  ``mailguard.cisco.com''.  
  \item    I also use a smart host so I uncommented that line ( deleted dnl )
\end{enumerate}
  
\break

\item  Now we produce new sendmail.cf
\begin{enumerate}
 \item cd /usr/share/sendmail-cf/cf
 \item m4 ../m4/cf.m4 mailguard.mc > mailguard.cf
 \item cp mailguard.cf /etc/mail
 \item cd /etc/mail
 \item mv sendmail.cf sendmail.cf-premg
 \item mv mailguard.cf sendmail.cf
 \item service sendmail restart
\end{enumerate}



\item  We have the mailguard code in place.  We have the
 sendmail.cf with the custom mailers in place.  That means this appliance
 machine is now ready to receive a mail to a configured list and then handle
 it.  In short, we're ready to take it out of demo mode and move to
 production mode.  Not too bad for just a few minutes' work?

\subsection*{Test the Sendmail / OS pairing} % (fold)
\label{sub:test_the_sendmail_os_pairing}


\item  We need to configure the production profile, this is handily stored in
 \$MGDIR/lib/EMS/Mailguard/Config.pm.  You'll notice different stanza's for
 different modes.  This was inspired by the Rails way of doing things, you
 will want to customize the PROD stanza.

\item    Configure and run the the demo, as a sanity check.  Our next steps are going to be around
   building the appliance out, we need to make sure that we're good thus far.  Pay notice, the reason the demo works is that
   there are many default values pre-configured in the DEMO bracket of Config.pm (see previous step). We're
   going to have to change some of these. 8)  -- don't worry, it's not too
   bad!

	\begin{enumerate}
		\item  \$ cd \$MGHOME/cmailguard
	  \item  \$ bin/loaddb
	\end{enumerate}
\nobreak
\vskip 0.25em  
	\textbf{Output:}
\nobreak	 
   \begin{verbatim}
	 
	   Warning, you are still in demo mode, turn off the demo flag if you're
	   working on a production deploy!  Alternatively give a fullpath to the
	   build location of your cacheDB.

	   Creating database as: /opt/mailguard/demo\_etc/lists.db
	   Incorporating mailguard-sample...
	 
   \end{verbatim}
	 
\break
   
        \item \$ bin/lookup\_in\_loaddb.pl mailguard-sample
     \nobreak
 				\vskip 0.25em  
					\textbf{Output:}
       \nobreak
 \begin{verbatim} $VAR1 = {
   'EXTESCROW' => 'Message for external people whose mail is being held.  ',
   'BARONS' => {
                 'kinghobo' => 1,\end{verbatim} \ldots

 
     \$ bin/mailguard.pl -f test\_messages/kinghobo\_baron\_test\_message -D -l mailguard-sample
   
   	\vskip 0.25em  
   		\textbf{Output:}
   		
      \begin{verbatim}
	
 DEBUG MODE Enabled
 DEMO MODE Enabled
 Disable DEMO MODE by setting DEMO\_MODE\_ENABLED to false
 Logging to: /opt/mailguard/log/mailguard.demo.log
 BEGIN Preparing database: /opt/mailguard/demo\_etc/lists.db
 Searching /opt/mailguard/demo\_etc/lists.db for specification
 Initializing MailguardSession object based on file
 Storing to /opt/mailguard/queue/mailguard-sample@2008.3.19-9:20:38.32211
 Reached DEBUG endpoint:  kinghobo, a barons-classified sender, 
 triggers behavior forward 
      \end{verbatim}
      
   \item  Edit /opt/mailguard/lib/EMS/Mailguard/Config.pm and take a look at the
    values in the DEMO stanza.  They should obviously match your environment.
   
   
   
   \item  Now we need to configure our tools to build for production.  The first we'll
     change is 'loaddb' - let's make it point to the right source.  We can fix
     this by honoring convention over configuration and simply changing the
     DEMO\_MODE variable to '' or any other Perl false value.
   
   \break

\item If we run loaddb at this point ( it's OK to try ) it will have an empty
size.  We don't have any source configuration data for the file.  So let's
take some of the demo data and mutate it slightly.
				
\begin{enumerate}
	\item  Copy \$MGHOME/demo\_lists/* to \$MGHOME/lists
	
	 
	 \item  Rename these files 'mailguard-test' and 'mailguard-test-barons'
	 respectively
	
	 
	 \item  Likewise, copy \$MGHOME/demo\_configs/mailguard-sample to\\
	 \$MGHOME/configs/mailguard-test
	
	 
	 \item  Now our loaddb will create a meaningful cacheDB
	
	 
	 \item \$ ../bin/loaddb
	
	 \begin{verbatim}
		 Creating database as: /opt/mailguard/etc/lists.db
		 Incorporating mailguard-test...
	 \end{verbatim}
	
\end{enumerate}
				
				

\item Since this DB is going to need to be read by the user the MTA runs as, we
need to make sure its group is 'mailguard' and that the permissions are
right.  


\item \$chgrp mailguard /opt/mailguard/etc/lists.db

\item \$chmod g+rx /opt/mailguard/etc/lists.db

\verb '-rw-r-xr--  1 stharms mailguard 8192 Mar 19 09:50 lists.db'

\item A handy verification tool is lookup\_in\_loaddb.pl, but we should change it
into prod mode.  Change the \$DEFAULT\_CACHEDB\_LOCATION to be your production
location (\$MGHOME/etc/lists.db).


\item We should also take this time, of course, to take the mailguard.pl file
itself out of demo mode!  Change the DEMO\_MODE\_ENABLED value to a false
value.
				 

\item  On a remote system run something to send some text to the mailguard address.

 \$cat ./deployment\_diary |mutt -s "Test message" mailguard-test@mg-whitebox.cisco.com

 If all goes well you've got a great basis for building out the Mailguard
 infrastructure that works best for you!  Great job!


\item  If something doesn't go quite right, well, then we get to start the
 debugging process. It's just a few tiny tweaks usually.

\break

\item If all goes well you should get a rejection message saying that you were
external and the rules say to reject external mail.  This matches the
configuration in MGDIR/etc/mailguard-test .  By changing parameters in the
Config file, we can change the behavior.

\begin{verbatim}
	Subject: [MAILGUARD REJECTED MESSAGE] RE: Test message
	X-Mailer: Mailguard 2.0
	Date: Wed, 19 Mar 2008 13:25:13 -0400
	To: stharms@cisco.com
	From: mailguard@demodomain.com
\end{verbatim}

\vskip 0.25em
\textbf{Output:}
\verb 'Message for external people whose mail is being rejected.'


\item Change 'our\_domain' to your actual domain in the Config.pm 'DEMO' stanza.

\item Change the configuration in \$MGDIR/configs/mailguard-test to say "reject" for
internal

\item Re-run loaddb 

\item Re-send a test message...

\begin{verbatim}
	Subject: [MAILGUARD REJECTED MESSAGE] RE: Test message
	X-Mailer: Mailguard 2.0
	Date: Wed, 19 Mar 2008 13:31:09 -0400
	To: stharms@cisco.com
	From: mailguard@YOURDOMAIN.com
\end{verbatim}

\vskip 0.25em
\textbf{Output:}

\verb 'Message for internal people whose mail is being rejected.'


\item Great, so now you have mail coming in, mailguard rules being recognized,
mailguard blurbs being sent out.  The only thing missing is to build up a web
server to manipulate your queue for escrowed messages.


\item First change the configuration such that internal senders' mail escrows by
editing the config file for mailguard-test and setting internal: to escrow.


\item Send another test message and your account should get notice of the escrow.

\vskip 0.25em
\textbf{Output:}
\begin{verbatim}
	Subject: [ MAILGUARD ESCROW NOTIFICATION ]: RE: Test message
	X-Mailer: Mailguard 2.0
	Date: Wed, 19 Mar 2008 13:33:38 -0400
	To: stharms@cisco.com
	From: mailguard@demodomain.com

	Message for internal people whose mail is being held.
\end{verbatim}

\item We now have a functioning system.  Now we need to allow our web server to view and manipulate the contents of the
mailguard queue.  

% subsection test_the_sendmail_os_pairing (end)

\subsection*{Installing / Configuring the Web Component} % (fold)
\label{sub:installing_web_component}
\begin{enumerate}


\item   Install a web server.  I used 'yum' to install Apache


\item   I then installed a basic index.html in the document root


\item   I then copied the CGI files in the SVN repository (
~/cmailguard/mailguard/web/*.cgi) into the cgi-bin directory of the
freshly-installed server.


\item  Add the 'apache' user ( or whichever user your web server runs as ) as a
member of the 'mailguard' group so that it can view and manipulate the
queue files that are generated by the application's
operation.


\item Then you want to take a look at the .../cgi-bin/review.cgi file.  The
configuration variable set for our implementation will look like this:

( \$MGPATH has been set by running CONFIGURE.sh at the first part of install ) 

\break

\begin{verbatim}
	# CONFIGURATION VARIABLES
	my %CONFIG = (

	 # Server Description
	 'servername' => 'mailguard',
	 'domain' => 'YOURDOMAIN.com',

	 # Mailguard Pathing
	 'logfile'     => "$MGPATH/mailguard/log/mailguard-web.log",
	 'queue_path'  => "$MGPATH/mailguard/queue",
	 'list_db'     => "$MGPATH/mailguard/etc/lists.db",

	 'cgi_method'  => "PUT",
	 'progname'    => "review",
	);

	$CONFIG{'myurl'}       = 
	  "http://$CONFIG{'servername'}.$CONFIG{domain}/cgi-bin/review.cgi",
	$CONFIG{'approveurl'}  = 
	  "http://$CONFIG{'servername'}.$CONFIG{domain}/cgi-bin/approve.cgi",


\end{verbatim}

You really only need to set two values, 'servername' and 'domain'.   Flipping
the cgi-method between get and put may be handy in your situation but PUT is
fine.  In accordance with our example, we're going to set these values to
'mailguard' and 'YOURDOMAIN.com'.



\item Similarly, you need to edit the approve.cgi file.  

\begin{verbatim}
	my %CONFIG = (
	   'xmlfile'    => "$MGPATH/mailguard/etc/mailguard_conf.xml",
	   'logfile'    => "$MGPATH/mailguard/log/web_log",
	   'queue_path' => "$MGPATH/mailguard/queue",
	   'list_db'    => "$MGPATH/mailguard/etc/lists.db",
	   'our_domain' => "YOUR DOMAIN HERE",
	   'myurl' => "CGI-BIN DIRECTORY FOR THESE SCRIPTS",
	   'basename' => "Mailguard",
	   'progname' => 'Mailguard:Approve.cgi',
	   'review_script' => 'review.cgi',
	   'approve_script' => 'approve.cgi'
	              );
\end{verbatim}
% subsection installing_web_component (end)


Again, you need only to do a tiny bit of work.  In this case, you want to set
the values of our\_domain and myurl. 'our\_domain' will be the same as the
previous script.  'myurl' should be set to the path to the cgi-bin directory
where review.cgi and approve.cgi live.

\end{enumerate}


\item If you now go to:

http://mailguard.YOURDOMAIN.com/cgi-bin/review.cgi?mailguard-test

You should see message whose escrow you were notified of sitting there in the queue.


\item You should then click on the subject line to take a look at the message.

You have options to help you decide if a given message is legitimate: you can
look at the headers (DETAILS), send yourself the message as an attachment (helpful when
you have multi-part mail), deny the message with the blurb back to the sender
(Spam), silently DELETE the message, and send it to the members of mailguard-test.

CAVEAT:

Since you're not currently actually 'logging' into these scripts, the HTTP user
that validates you doesn't have a name.  That's why when you review a message
it says <blank> is reviewing.  If you wind up using .htaccess to get this user
value as I do, then this value will get filled in for you.  Otherwise you will
need to do a little bit of code tweaking.

Naturally, as this name is unknown, if you try to run 'preview' it won't work
because, well it won't know who to send it to.

Lastly, if you try approve, I'm pretty sure the members of mailguard-test \\
(/opt/mailguard/lists/mailguard-test) don't exist in your environment.  If you
wanted to do some more meaningful testing, you could add a test GMail account
or something as a member.


\section*{CONCLUSION} % (fold)
\label{sec:section_name}

And that's pretty much it, you now have the basics covered of a mailguard
appliance.  There will be some configuration that you will do, but most of
these will be system or application level configurations, you won't need to
tweak this code (I hope!) too much.

Change the it as you see fit and if you have some great additions, check them
back into subversion :).

% section CONCLUSION (end)

\section*{AUTHOR} % (fold)
Steven G. Harms\\
Cisco Inc.
(\verb'stharms@cisco.com')
\vskip 0.5em
\textbf{Personal URL:}  \underline{http://www.stevengharms.com} \\
(opinions reflected there do not represent my employer)
\label{sec:AUTHOR}

% section AUTHOR (end)

\end{enumerate}
% subsection source_retrieval_and_os_configuration (end)
\label{sec:step_by_step_installation}










\end{document}